﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.DataAccess.Client;
using System.Configuration;
using Wicresoft.UnifyShow.Business;

namespace Wicresoft.UnifyShow.BusinessImpl
{
    public class ModelHelper<T>
    {

        private static string GetModelDBName()
        {
            Type t = typeof(T);
            string tableName = string.Empty;
            foreach (Attribute attr in Attribute.GetCustomAttributes(t))
            {
                if (attr.GetType() == typeof(DatabaseTableInfoAttribute))
                    tableName = ((DatabaseTableInfoAttribute)attr).TableName;
            }
            if (String.IsNullOrWhiteSpace(tableName)) throw new Exception("Model Error No Class DatabaseTableInfoAttribute");
            return tableName;
        }

        public static List<T> GetModel_By_QueryParams(IList<QueryParameter> param, IList<OrderbyParameter> orderBy, Nullable<int> ps,
            Nullable<int> pi, OracleDataAccess oda, JoinCauses joins = null, IList<string> listColumns = null)
        {

            string tableName = GetModelDBName();

            DBMType type = DBMType.select;
            string sqlStr = SQLHelper.PrepareSqlStr(type, tableName, param, orderBy, ps, pi, joins);
            List<OracleParameter> commandParameters = SQLHelper.PrepareOracleParameter(param, tableName);
            if (joins != null)
            {
                foreach (var item in joins.Get())
                {
                    commandParameters.AddRange(SQLHelper.PrepareOracleParameter(item.GetQueryParameter().ToArray(), item.TableName));
                }
            }
            using (OracleDataReader dr = oda.ExecuteReader(sqlStr, commandParameters))
            {
                if (listColumns == null)
                {
                    return AutoMapper.Map<OracleDataReader, T>(dr);
                }
                else
                {
                    return AutoMapper.Map<OracleDataReader, T>(dr, listColumns);
                }
            }
        }


        public static int CreateModel_By_QueryParams(IList<QueryParameter> param, OracleDataAccess oda)
        {

            string tableName = GetModelDBName();
            DBMType type = DBMType.insert;
            string sqlStr = SQLHelper.PrepareSqlStr(type, tableName, param, null, null, null);
            List<OracleParameter> commandParameters = SQLHelper.PrepareOracleParameter(param, tableName);
            return oda.ExecuteCommand(sqlStr, commandParameters);
        }

        public static Decimal GetModelCount_By_QueryParams(IList<QueryParameter> param, OracleDataAccess oda, JoinCauses joins = null)
        {

            string tableName = GetModelDBName();
            DBMType type = DBMType.count;
            string sqlStr = SQLHelper.PrepareSqlStr(type, tableName, param, null, null, null, joins);
            List<OracleParameter> commandParameters = SQLHelper.PrepareOracleParameter(param, tableName);
            if (joins != null)
            {
                foreach (var item in joins.Get())
                {
                    commandParameters.AddRange(SQLHelper.PrepareOracleParameter(item.GetQueryParameter().ToArray(), item.TableName));
                }
            }
            return (Decimal)oda.ExecuteScalar(sqlStr, commandParameters);
        }

        public static int UpdateModel_By_QueryParams(IList<QueryParameter> where, T model, IList<string> exceptString,
            OracleDataAccess oda, JoinCauses joins = null)
        {
            IList<QueryParameter> all = where.Concat(AutoMapper.GenerateUpdateSome(model, exceptString)).ToList();
            string tableName = GetModelDBName();
            DBMType type = DBMType.update;
            string sqlStr = SQLHelper.PrepareSqlStr(type, tableName, all, null, null, null, joins);
            List<OracleParameter> commandParameters = SQLHelper.PrepareOracleParameter(all, tableName);
            if (joins != null)
            {
                foreach (var item in joins.Get())
                {
                    commandParameters.AddRange(SQLHelper.PrepareOracleParameter(item.GetQueryParameter().ToArray(), item.TableName));
                }
            }
            return (int)oda.ExecuteCommandWithTransaction(sqlStr, commandParameters);
        }

        public static int AddModel_By_QueryParams(T model, IList<string> exceptString, OracleDataAccess oda, JoinCauses joins = null)
        {
            IList<QueryParameter> all = AutoMapper.GenerateInsertSome(model, exceptString).ToList();
            string tableName = GetModelDBName();
            DBMType type = DBMType.insert;
            string sqlStr = SQLHelper.PrepareSqlStr(type, tableName, all, null, null, null, joins);
            List<OracleParameter> commandParameters = SQLHelper.PrepareOracleParameter(all, tableName);
            if (joins != null)
            {
                foreach (var item in joins.Get())
                {
                    commandParameters.AddRange(SQLHelper.PrepareOracleParameter(item.GetQueryParameter().ToArray(), item.TableName));
                }
            }
            return (int)oda.ExecuteCommand(sqlStr, commandParameters);
        }

        public static int AddListModel_By_QueryParams(IList<T> models, IList<string> exceptString, OracleDataAccess oda, JoinCauses joins = null)
        {
            OracleTransaction trans = oda.BeginTransaction();
            try
            {
                foreach (var item in models)
                {
                    AddModel_By_QueryParams(item, exceptString, oda);
                }
                trans.Commit();
                return 1;
            }
            catch (Exception e) { trans.Rollback(); return 0; }
        }

        public static List<T> GetModel_By_DirectSql(string sql, IList<OracleParameter> parems, OracleDataAccess oda, IList<string> listColumns = null)
        {
            using (OracleDataReader dr = oda.ExecuteReader(sql, parems))
            {
                if (listColumns == null)
                {
                    return AutoMapper.Map<OracleDataReader, T>(dr);
                }
                else
                {
                    return AutoMapper.Map<OracleDataReader, T>(dr, listColumns);
                }
            }
        }

        public static List<T> GetModel_By_OracleDataReader(OracleDataReader dr)
        {
            using (dr)
            {
                return AutoMapper.Map<OracleDataReader, T>(dr).ToList();
            }
        }


        public static int CreateModel_By_DirectSql(string sql, IList<OracleParameter> parems, OracleDataAccess oda)
        {
            return oda.ExecuteCommandWithTransaction(sql, parems);
        }

        public static Decimal GetModelCount_By_DirectSql(string sql, IList<OracleParameter> parems, OracleDataAccess oda)
        {
            return (Decimal)oda.ExecuteScalar(sql, parems);
        }

        public static string GetModelSomeInfo_By_DirectSql(string sql, IList<OracleParameter> parems, OracleDataAccess oda)
        {
            return (string)oda.ExecuteScalar(sql, parems);
        }

        public static int UpdateOrDeleteModel_By_DirectSql(string sql, IList<OracleParameter> parems, OracleDataAccess oda)
        {
            return oda.ExecuteCommandWithTransaction(sql, parems);
        }

        //public static List<QueryParameter> CreateQueryParameterByExampleModel(T t)
        //{
        //    List<QueryParameter> result = new List<QueryParameter>();
        //    Type type = t.GetType();
        //    foreach (var item in type.GetProperties())
        //    {
        //        item.GetValue(t,null);
        //    }

        //}


    }
}
